﻿using System.Collections.Generic;
using System.Linq;
using Certify.SourceGenerators;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SourceGenerator;

namespace Certify.Core.Tests.Unit
{
    [TestClass]
    public class ApiMethodsTests
    {
        [TestMethod]
        public void EachApiMethod_HasRequiredPermissions_AndMockPrincipalCanAccess()
        {
            var apiDefs = ApiMethods.GetApiDefinitions();
            foreach (var api in apiDefs)
            {
                // For each endpoint, create a mock security principal with only the required permissions
                var requiredPerms = api.RequiredPermissions;
                Assert.IsNotNull(requiredPerms, $"API {api.OperationName} should have RequiredPermissions");
                Assert.IsNotEmpty(requiredPerms, $"API {api.OperationName} should have at least one RequiredPermission");

                // Simulate a principal with exactly these permissions
                var mockPrincipal = new MockSecurityPrincipal(requiredPerms);

                // Simulate an authorization check for each required permission
                foreach (var perm in requiredPerms)
                {
                    Assert.IsTrue(mockPrincipal.HasPermission(perm), $"Mock principal should have permission {perm.ResourceType}:{perm.Action} for {api.OperationName}");
                }
            }
        }

        [TestMethod]
        public void EachApiMethod_RequiredPermissionsMatchesStandardAction()
        {
            var standardActions = Models.Hub.Policies.GetStandardResourceActions();

            var apiDefs = ApiMethods.GetApiDefinitions();
            foreach (var api in apiDefs)
            {

                // For each endpoint, create a mock security principal with only the required permissions
                var requiredPerms = api.RequiredPermissions;

                // check standard actions have a matching resource type and action defined
                foreach (var perm in requiredPerms)
                {
                    Assert.IsTrue(standardActions.Any(a => a.ResourceType == perm.ResourceType && a.Id == perm.Action),
                        $"Standard action {perm.ResourceType}:{perm.Action} not found for API {api.OperationName}");
                }
            }
        }
    }

    // Simple mock for demonstration
    public class MockSecurityPrincipal
    {
        private readonly List<PermissionSpec> _perms;
        public MockSecurityPrincipal(List<PermissionSpec> perms)
        {
            _perms = perms;
        }
        public bool HasPermission(PermissionSpec perm)
        {
            return _perms.Any(p => p.ResourceType == perm.ResourceType && p.Action == perm.Action);
        }
    }
}
